<?php

namespace App\Jobs;

use App\Models\Common\Constant;
use App\Models\Common\FactoryHandler;
use App\Models\Coupon\Coupon;
use App\Models\Coupon\CouponOrder;
use App\Models\Merchant\Merchant;
use App\Models\Merchant\MerchantBalanceLog;
use App\Models\Merchant\MerchantCoupon;
use App\Models\Merchant\MerchantCouponLog;
use App\Models\Merchant\MerchantCouponReceiveLog;
use App\Models\Merchant\MerchantOrder;
use App\Models\ParkingLot\Lane;
use App\Models\ParkingLot\LaneOpenLog;
use App\Models\ParkingLot\MthOrder;
use App\Models\ParkingLot\ParkAreaLog;
use App\Models\ParkingLot\ParkEnterLog;
use App\Models\ParkingLot\ParkOrder;
use App\Models\ParkingLot\ParkOutLog;
use App\Models\Payment\PaymentOrder;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class PaymentOrderPaid implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    private $paymentOrder;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct(PaymentOrder $paymentOrder)
    {
        $this->paymentOrder = $paymentOrder;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        $paymentOrder = $this->paymentOrder;

        $paymentOrder->refresh();

        if ($paymentOrder->order_status !== Constant::ORDER_STATUS_PAID) {
            return;
        }

        switch ($paymentOrder->related_type) {
            case ParkOrder::class:
                self::parkOrder($paymentOrder);
                break;
        }
    }

    private function parkOrder(PaymentOrder $paymentOrder)
    {
        $orderType = '临停订单';
        /** @var ParkOrder $order */
        if (!$order = $paymentOrder->related) {
            \Log::error($orderType.'支付回调 未查找到订单', [
                'paid_code' => $paymentOrder->paid_code
            ]);
            return false;
        }

        $paySuccess = false;
        try {
            \DB::beginTransaction();

            if (Constant::ORDER_STATUS_PAID !== $order->order_status) {
                if (\Str::startsWith($paymentOrder->pay_type, 'ALI') || \Str::startsWith($paymentOrder->trade_type, 'ALI')) {
                    $payType = Constant::PAY_TYPE_ALIPAY;
                } else {
                    $payType = Constant::PAY_TYPE_WECHATPAY;
                }
                $order->order_status = Constant::ORDER_STATUS_PAID;
                $order->paid_at = $paymentOrder->paid_at;
                $order->out_trade_no = $paymentOrder->out_trade_no;
                $order->pay_type = $payType;

                // 支付回调期间可能会触发临停重新计费
                if ($order->final_amount !== $paymentOrder->amount) {
                    if ($order->final_amount === $order->total_amount) {
                        $order->total_amount = $paymentOrder->amount;
                    }
                    $order->final_amount = $paymentOrder->amount;
                }

                $order->save();
                $paySuccess = true;
            } else {
                \Log::warning($orderType.'重复支付回调', [
                    'order_code' => $order->order_code,
                    'paid_code' => $paymentOrder->paid_code,
                    'order_title' => $order->order_title,
                ]);
            }

            \DB::commit();
        } catch (\Exception $exception) {
            \DB::rollBack();
            \Log::error($orderType.'支付回调处理 更新失败', [
                'order_code' => $order->order_code,
                'order_title' => $order->order_title,
                'error' => $exception->getMessage(),
            ]);
        } finally {
            if ($paySuccess) {

                /** @var ParkEnterLog $parkEnterLog */
                if (!$parkEnterLog = $order->related) {
                    \Log::error($orderType.'支付回调处理 未查找到在场记录', [
                        'order_code' => $order->order_code,
                        'order_title' => $paymentOrder->order_title,
                    ]);
                    return false;
                }

                \Log::channel('parking')->info('订单支付成功', [
                    'order_code' => $order->order_code,
                    'car_no' => $parkEnterLog->car_no
                ]);

                $success = false;
                try {
                    \DB::beginTransaction();

                    // 更新内场区域计费记录
                    ParkAreaLog::where(['main_log_id' => $parkEnterLog->id, 'is_charge' => 1])->each(function ($areaLog) {
                        $areaLog->update(['is_paid' => 1]);
                    });

                    // 更新优惠券
                    if ($order->coupon_amount && $order->coupons) {
                        $coupons = $order->coupons;
                        $couponIds = array_column($coupons, 'id');
                        $couponArr = array_column($coupons, null, 'id');
                        MerchantCouponReceiveLog::whereIn('id', $couponIds)->each(function ($receiveLog) use ($order, $couponArr) {
                            $receiveLog->update([
                                'write_off_at' => now(),
                                'status' => 2,
                                'data' => [
                                    'amount' => \Arr::get($couponArr[$receiveLog->id], 'amount', 0),
                                    'seconds' => \Arr::get($couponArr[$receiveLog->id], 'seconds', 0),
                                ]
                            ]);
                        });
                    }

                    $success = true;
                    \DB::commit();
                } catch (\Exception $exception) {
                    \DB::rollBack();
                    \Log::error($orderType.'支付回调处理 未查找到在场记录', [
                        'order_code' => $order->order_code,
                        'order_title' => $order->order_title,
                        'error' => $exception->getMessage(),
                    ]);
                } finally {
                    if ($success) {

                    }
                }
            }
        }
    }
}
